
local Element = import("../Element/Element.lua");

local StyleSheet = import("../Style/StyleSheet.lua");
local Scope = import("../Script/Scope.lua");

local Widget = commonlib.inherit(Element);

Widget:Property("XmlPath");     -- xml 文件路径
Widget:Property("StyleSheet");             


function Widget:ctor()
    self:SetName("Widget");

    self.__style_sheet__ = nil;   -- 样式表
    self.__env__ = nil;           -- 脚本环境
    self.__scope__ = nil;
end

function Widget:Init(xmlnode, window, parent)
    self:InitElement(xmlnode, window, parent);

    if (parent) then
        self.__style_sheet__ = parent:GetStyleSheet():Clone();
        self.__scope__ = Scope(parent:GetScope());
    else
        self.__style_sheet__ = StyleSheet:new():Init();
        self.__scope__ = Scope(window:GetRootScope());
    end

    self:ExtendScope();
    
    self:InitChildrenElement(xmlnode, window, parent);

    return self;
end

function Widget:InitChildrenElement(xmlnode, window, parent)
    local template = self:GetAttrStringValue("template");
    local url = self:GetAttrStringValue("url");
    
    xmlnode.external_childrens = {};
    xmlnode.internal_childrens = {};
    
    if (template == "" and url == "") then url = self:GetXmlPath() or "" end 
    if (template == "" and url ~= "") then template = commonlib.GetFileText(url) or "" end 
    if (template == "") then return end 

    -- 维持脚本原本格式
    template = string.gsub(template, "[\r\n]<script(.-)>(.-)[\r\n]</script>", "<script%1>\n<![CDATA[\n%2\n]]>\n</script>");
   
    local xmlnodes = commonlib.XmlDecode(template);
    
    if (xmlnodes) then 
        for index, subnode in ipairs(xmlnodes) do 
            if (subnode.name == "style") then
                self:LoadStyle(subnode);
            elseif (subnode.name == "script") then
                self:LoadScript(subnode);
            else 
                xmlnode.external_childrens[index] = subnode;
            end
        end
    else
        print("Error: XmlDecode Failed", url, template);
    end 

    local size = #xmlnode;
    for i = 1, size do
        xmlnode.internal_childrens[i] = xmlnode[i];
        xmlnode[i] = nil;
    end

    local child_xmlnodes = xmlnodes and xmlnode.external_childrens or xmlnode.internal_childrens;
    local __xmlnodes__ = {};
    -- 优先加载 style script 标签
    for _, child_xmlnode in ipairs(child_xmlnodes) do
        if (child_xmlnode.name == "style") then
            self:LoadStyle(child_xmlnode);
        elseif (child_xmlnode.name == "script") then
            self:LoadScript(child_xmlnode);
        else 
            table.insert(__xmlnodes__, child_xmlnode);
        end
    end

    for _, child_xmlnode in ipairs(__xmlnodes__) do
        self:AddChildren(self:CreateElement(child_xmlnode, window, self));
    end
end

function Widget:LoadStyle(xmlnode)
    self:GetStyleSheet():LoadString(self:GetXmlNodeText(xmlnode));
end

function Widget:LoadScript(xmlnode)
    commonlib.dostring(self:GetXmlNodeText(xmlnode), self:GetScope());
end

function Widget:GetStyleSheet()
    return self.__style_sheet__;
end

function Widget:GetScope()
    return self.__scope__;
end

function Widget:GetElementDefaultClass()
    return Widget;
end

function Widget:ExtendScope()
    self.__scope__.RegisterWidget = function(tagname, filename)
        self:RegisterWidget(tagname, filename);
    end

    self.__scope__.RemoveWidget = function(tagname)
        self:RemoveWidget(tagname);
    end
end

function Widget:RegisterWidget(tagname, filename)
    if (type(filename) ~= "string") then return end 
    local WidgetClass = commonlib.inherit(Widget);
    WidgetClass:SetXmlPath(filename);
    self:RegisterElementClass(tagname, WidgetClass);
end

function Widget:RemoveWidget(tagname)
    self:RemoveElementClass(tagname);
end

return Widget;